﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Editor.SpanEditHandler
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using Microsoft.Internal.Web.Utils;
using System.Collections.Generic;
using System.Linq;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Text;
using System.Web.Razor.Tokenizer.Symbols;

namespace System.Web.Razor.Editor
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Provides methods for handling the span edits.</summary>
  public class SpanEditHandler
  {
    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Initializes a new instance of the <see cref="T:System.Web.Razor.Editor.SpanEditHandler" /> class.</summary>
    /// <param name="tokenizer">The method used to parse string into tokens.</param>
    public SpanEditHandler(Func<string, IEnumerable<ISymbol>> tokenizer)
      : this(tokenizer, AcceptedCharacters.Any)
    {
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Initializes a new instance of the <see cref="T:System.Web.Razor.Editor.SpanEditHandler" /> class.</summary>
    /// <param name="tokenizer">The method used to parse string into tokens.</param>
    /// <param name="accepted">One of the values of the <see cref="T:System.Web.Razor.Parser.SyntaxTree.AcceptedCharacters" /> enumeration.</param>
    public SpanEditHandler(
      Func<string, IEnumerable<ISymbol>> tokenizer,
      AcceptedCharacters accepted)
    {
      this.AcceptedCharacters = accepted;
      this.Tokenizer = tokenizer;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets a value that specifies the accepted characters.</summary>
    /// <returns>One of the values of the <see cref="T:System.Web.Razor.Parser.SyntaxTree.AcceptedCharacters" /> enumeration.</returns>
    public AcceptedCharacters AcceptedCharacters { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the editor hints.</summary>
    /// <returns>The editor hints.</returns>
    public EditorHints EditorHints { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets or sets the method used to parse string into tokens. </summary>
    /// <returns>The method used to parse string into tokens.</returns>
    public Func<string, IEnumerable<ISymbol>> Tokenizer { get; set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Creates a new default span edit handler.</summary>
    /// <returns>A newly created default span edit handler.</returns>
    public static SpanEditHandler CreateDefault() => SpanEditHandler.CreateDefault((Func<string, IEnumerable<ISymbol>>) (s => Enumerable.Empty<ISymbol>()));

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Creates a new default span edit handler.</summary>
    /// <returns>A newly created default span edit handler.</returns>
    /// <param name="tokenizer">The method used to parse string into tokens.</param>
    public static SpanEditHandler CreateDefault(
      Func<string, IEnumerable<ISymbol>> tokenizer)
    {
      return new SpanEditHandler(tokenizer);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Applies the text change to the span.</summary>
    /// <returns>The result of the apply operation.</returns>
    /// <param name="target">The span to apply changes to.</param>
    /// <param name="change">The change to apply.</param>
    public virtual EditResult ApplyChange(Span target, TextChange change) => this.ApplyChange(target, change, false);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Applies the text change to the span.</summary>
    /// <returns>The result of the apply operation.</returns>
    /// <param name="target">The span to apply changes to.</param>
    /// <param name="change">The change to apply.</param>
    /// <param name="force">true to accept partial result; otherwise, false.</param>
    public virtual EditResult ApplyChange(Span target, TextChange change, bool force)
    {
      PartialParseResult result = PartialParseResult.Accepted;
      TextChange normalizedChange = change.Normalize();
      if (!force)
        result = this.CanAcceptChange(target, normalizedChange);
      return result.HasFlag((Enum) PartialParseResult.Accepted) ? new EditResult(result, this.UpdateSpan(target, normalizedChange)) : new EditResult(result, new SpanBuilder(target));
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the span owns the specified change.</summary>
    /// <returns>true if the span owns the specified change; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to check.</param>
    public virtual bool OwnsChange(Span target, TextChange change)
    {
      int num1 = target.Start.AbsoluteIndex + target.Length;
      int num2 = change.OldPosition + change.OldLength;
      if (change.OldPosition < target.Start.AbsoluteIndex)
        return false;
      if (num2 < num1)
        return true;
      return num2 == num1 && (uint) this.AcceptedCharacters > 0U;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the span can accept the specified change.</summary>
    /// <returns>true if the span can accept the specified change; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="normalizedChange">The change to apply.</param>
    protected virtual PartialParseResult CanAcceptChange(
      Span target,
      TextChange normalizedChange)
    {
      return PartialParseResult.Rejected;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Updates the span using the normalized change.</summary>
    /// <returns>The new span builder for the specified target.</returns>
    /// <param name="target">The span to update.</param>
    /// <param name="normalizedChange">The normalized change.</param>
    protected virtual SpanBuilder UpdateSpan(Span target, TextChange normalizedChange)
    {
      string newContent = normalizedChange.ApplyChange(target);
      SpanBuilder spanBuilder = new SpanBuilder(target);
      spanBuilder.ClearSymbols();
      foreach (ISymbol symbol in this.Tokenizer(newContent))
      {
        symbol.OffsetStart(target.Start);
        spanBuilder.Accept(symbol);
      }
      if (target.Next != null)
      {
        SourceLocation newLocation = SourceLocationTracker.CalculateNewLocation(target.Start, newContent);
        target.Next.ChangeStart(newLocation);
      }
      return spanBuilder;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified change is at the end of first line of the span content.</summary>
    /// <returns>true if the specified change is at the end of first line of the span content; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to check.</param>
    protected internal static bool IsAtEndOfFirstLine(Span target, TextChange change)
    {
      int num = target.Content.IndexOfAny(new char[4]
      {
        '\r',
        '\n',
        '\u2028',
        '\u2029'
      });
      return num == -1 || change.OldPosition - target.Start.AbsoluteIndex <= num;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified change is at the end the span content and for insertion.</summary>
    /// <returns>true if the specified change is at the end the span content and for insertion; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to check.</param>
    protected internal static bool IsEndInsertion(Span target, TextChange change) => change.IsInsert && SpanEditHandler.IsAtEndOfSpan(target, change);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified change is at the end the span content and for deletion.</summary>
    /// <returns>true if the specified change is at the end the span content and for deletion; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to check.</param>
    protected internal static bool IsEndDeletion(Span target, TextChange change) => change.IsDelete && SpanEditHandler.IsAtEndOfSpan(target, change);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified change is at the end the span content and for replacement.</summary>
    /// <returns>true if the specified change is at the end the span content and for replacement; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to check.</param>
    protected internal static bool IsEndReplace(Span target, TextChange change) => change.IsReplace && SpanEditHandler.IsAtEndOfSpan(target, change);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether the specified change is at the end of the span.</summary>
    /// <returns>true if the specified change is at the end of the span; otherwise, false.</returns>
    /// <param name="target">The span to check.</param>
    /// <param name="change">The change to chek.</param>
    protected internal static bool IsAtEndOfSpan(Span target, TextChange change) => change.OldPosition + change.OldLength == target.Start.AbsoluteIndex + target.Length;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Gets the old text from the span content.</summary>
    /// <returns>The old text from the span content.</returns>
    /// <param name="target">The span to get old text from.</param>
    /// <param name="change">The text change which contains the location of the old text.</param>
    protected internal static string GetOldText(Span target, TextChange change) => target.Content.Substring(change.OldPosition - target.Start.AbsoluteIndex, change.OldLength);

    internal static bool IsAdjacentOnRight(Span target, Span other)
    {
      SourceLocation start1 = target.Start;
      int absoluteIndex1 = start1.AbsoluteIndex;
      start1 = other.Start;
      int absoluteIndex2 = start1.AbsoluteIndex;
      if (absoluteIndex1 >= absoluteIndex2)
        return false;
      SourceLocation start2 = target.Start;
      int num = start2.AbsoluteIndex + target.Length;
      start2 = other.Start;
      int absoluteIndex3 = start2.AbsoluteIndex;
      return num == absoluteIndex3;
    }

    internal static bool IsAdjacentOnLeft(Span target, Span other)
    {
      SourceLocation start1 = other.Start;
      int absoluteIndex1 = start1.AbsoluteIndex;
      start1 = target.Start;
      int absoluteIndex2 = start1.AbsoluteIndex;
      if (absoluteIndex1 >= absoluteIndex2)
        return false;
      SourceLocation start2 = other.Start;
      int num = start2.AbsoluteIndex + other.Length;
      start2 = target.Start;
      int absoluteIndex3 = start2.AbsoluteIndex;
      return num == absoluteIndex3;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Returns the string representation of the span edit handler.</summary>
    /// <returns>The string representation of the span edit handler.</returns>
    public override string ToString() => this.GetType().Name + ";Accepts:" + (object) this.AcceptedCharacters + (this.EditorHints == EditorHints.None ? (object) string.Empty : (object) (";Hints: " + this.EditorHints.ToString()));

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Determines whether this instance is equal to a specified object.</summary>
    /// <returns>true if the object is equal to the this instance; otherwise, false.</returns>
    /// <param name="obj">The object to compare with this instance.</param>
    public override bool Equals(object obj) => obj is SpanEditHandler spanEditHandler && this.AcceptedCharacters == spanEditHandler.AcceptedCharacters && this.EditorHints == spanEditHandler.EditorHints;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code. Returns the hash code for this instance.</summary>
    /// <returns>The hash code for this instance.</returns>
    public override int GetHashCode() => HashCodeCombiner.Start().Add((object) this.AcceptedCharacters).Add((object) this.EditorHints).CombinedHash;
  }
}
